/*
 * dht11.c
 *
 *  Created on: Mar 9, 2014
 *      Author: Trong Than
 */
#include <stdint.h>
#include <stdbool.h>

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_sysctl.h"
#include "inc/tm4c123gh6pm.h"

#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/rom.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom_map.h"

#include "source/dht11Lib/dht11.h"

#include "source/TimerDelay/timerdelay.h"

void DHT11_Init(tDHT11 DHT11 ){
	 if(DHT11.ui32GPIOPort==GPIO_PORTA_BASE){MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);}
    else if(DHT11.ui32GPIOPort==GPIO_PORTB_BASE){MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);}
    else if(DHT11.ui32GPIOPort==GPIO_PORTC_BASE){MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);}
    else if(DHT11.ui32GPIOPort==GPIO_PORTD_BASE){MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);}
    else if(DHT11.ui32GPIOPort==GPIO_PORTE_BASE){MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);}
    else if(DHT11.ui32GPIOPort==GPIO_PORTF_BASE){MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);}
}

void DHT11_Delay_us(uint8_t TimeWait){
	TimerDelayus(TimeWait);
	//SysCtlDelay((SysCtlClockGet()*TimeWait)/3000000);
}

void DHT11_Delay_ms(uint8_t TimeWait){
	TimerDelayms(TimeWait);
	//SysCtlDelay((SysCtlClockGet()*TimeWait)/3000);
}
/*
 * Set pinMode is Output
 */
void DHT11_PinModeOutput(tDHT11* DHT11){
	ROM_GPIOPinTypeGPIOOutput (DHT11->ui32GPIOPort ,DHT11->ui32GPIOPin);
}
/*
 * Set pinMode is Input
 */
void DHT11_PinModeInput(tDHT11* DHT11){
	ROM_GPIOPinTypeGPIOInput ( DHT11->ui32GPIOPort ,DHT11->ui32GPIOPin);
}
/*
 * Return DHT11_pin's State in other to get data from DHT11 sensor 
 */
int32_t DHT11_PinRead(tDHT11* DHT11){
	return (ROM_GPIOPinRead(DHT11->ui32GPIOPort ,DHT11->ui32GPIOPin));
}
/*
 * Write IO pin high or Low in other to control DHT11's data_pin 
 */
void DHT11_PinWrite(tDHT11* DHT11, bool State){
	ROM_GPIOPinWrite(DHT11->ui32GPIOPort ,DHT11->ui32GPIOPin,\
                	State? DHT11->ui32GPIOPin: ~DHT11->ui32GPIOPin);
}
/*
 * get data from DHT11 sensor
 */
bool DHT11_GetData(tDHT11* DHT11){

    uint8_t buffer[5]={0,0,0,0,0};
    uint8_t ii,i,checksum;

    DHT11_PinModeOutput(DHT11);      // out
    DHT11_PinWrite(DHT11,ON);        // up 1
    DHT11_Delay_us(60);              // delay(60us)
    // MCU sent start signal
    DHT11_PinWrite(DHT11,OFF);       // down 0
    DHT11_Delay_ms(20);              // delay(20ms) must >18ms
    DHT11_PinWrite(DHT11,ON);        // up 1
    // MCU waitting DHT11 response
    DHT11_PinModeInput(DHT11);       // in
    DHT11_Delay_us(60);              // delay(60us)
    if(DHT11_PinRead(DHT11)){
      return DHT11_ERROR;    // read 1 --> error
    }  
    else{
      while(!(DHT11_PinRead(DHT11)));       // wait get data
      DHT11_Delay_us(60);                   // delay(60us)
    }
    if(!DHT11_PinRead(DHT11)){
      return DHT11_ERROR;    // read 0 --> error
    }
    else 
      while(DHT11_PinRead(DHT11));       // wait get data
      for(i=0;i<5;i++)
      {
        for(ii=0;ii<8;ii++)
        {
          while(!DHT11_PinRead(DHT11));
          DHT11_Delay_us(50);
          if(DHT11_PinRead(DHT11))
              {
               buffer[i]|=(1<<(7-ii));
               while(DHT11_PinRead(DHT11));
              }
        }
      }
    checksum = buffer[0]+buffer[1]+buffer[2]+buffer[3];
    if((checksum)!=buffer[4]){
      return DHT11_ERROR;
    }
		else{   
		  DHT11->IntHumidity     =   buffer[0];
		  DHT11->DecHumidity     =   buffer[1];
      DHT11->IntTemperature  =   buffer[2];
		  DHT11->DecTemperature  =   buffer[3];
      return DHT11_SUCCESS;
		}
}